package com.mystnihon.tdroid.view.fragment;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import org.json.mine.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import ca.benow.transmission.model.TorrentStatus;
import ca.benow.transmission.model.TorrentStatus.TStatus;

import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.mystnihon.tdroid.R;
import com.mystnihon.tdroid.application.TDroidApplication;
import com.mystnihon.tdroid.config.Config;
import com.mystnihon.tdroid.manager.TransmissionManager;
import com.mystnihon.tdroid.manager.TransmissionManager.TransmissionResult;
import com.mystnihon.tdroid.manager.TransmissionManager.TransmissionResult.ActionType;
import com.mystnihon.tdroid.manager.TransmissionManager.TransmissionResult.ResultType;
import com.mystnihon.tdroid.view.FileChooserActivity;
import com.mystnihon.tdroid.view.SettingsActivity;
import com.mystnihon.tdroid.view.TorrentActivity;

public class TorrentsListFragment extends SherlockListFragment implements Observer {
	private static final int MESSAGE_ID = 0;

	private static final String STATE_LAST_REFRESH_TIME = "lastrefreshTime";

	private static final String STATE_TORRENTS = "torrents";
	private static final String TAG = TorrentsListFragment.class.getSimpleName();

	private TransmissionManager mManager;
	private TorrentListAdapter mTorrentListAdapter;
	private ArrayList<TorrentStatus> mTorrents;
	protected ArrayList<Observable> mLstObservable;

	private boolean mForceLocalFileDeletion = false;
	private long mLastRefreshTime = 0;
	private long mRefreshTime = 30;
	private boolean mUpdateSettingsAlreadyShown = false;

	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			if (msg.what == MESSAGE_ID) {
				Log.d("mLastRefreshTime", "Handle message");
				refresh();
			}
			// super.handleMessage(msg);
		};

	};
	MenuItem refresh;
	MenuItem settings;

	MenuItem upload;

	public TorrentsListFragment() {
		mLstObservable = new ArrayList<Observable>();

	}

	@SuppressWarnings("unchecked")
	// It's checked dumbass.
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		mManager = ((TDroidApplication) getSherlockActivity().getApplication()).getAppManager()
				.getTransmissionManager();
		mTorrentListAdapter = new TorrentListAdapter(getSherlockActivity());

		setListAdapter(mTorrentListAdapter);
		getListView().setOnItemLongClickListener(mTorrentListAdapter);
		getListView().setOnItemClickListener(mTorrentListAdapter);

		mLstObservable.add(mManager);

		if (savedInstanceState != null) {
			Object data = savedInstanceState.getSerializable(STATE_TORRENTS);
			if (data != null && data instanceof ArrayList) {
				mTorrents = transform((ArrayList<String>) data);
				mTorrentListAdapter.setTorrents(mTorrents);
			}
			mLastRefreshTime = savedInstanceState.getLong(STATE_LAST_REFRESH_TIME);
		} else {
			mLastRefreshTime = 0;
		}
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d("mLastRefreshTime", "onActiCreated:\t" + mLastRefreshTime);
		}
		setHasOptionsMenu(true);
		getSherlockActivity().setSupportProgressBarIndeterminateVisibility(false);
		super.onActivityCreated(savedInstanceState);
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == FileChooserActivity.REQUEST_CHOOSE_FILE && resultCode == Activity.RESULT_OK) {
			Uri uri = (Uri) data.getParcelableExtra(FileChooserActivity.EXTRA_RESPONSE_URI);
			if (uri != null) {
				mManager.addTorrent(uri);
			}
		}
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

		refresh = menu.add(0, 1, 1, R.string.action_refresh).setIcon(R.drawable.ic_menu_refresh)
				.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);

		upload = menu.add(0, 2, 2, R.string.action_add_a_torrent).setIcon(R.drawable.ic_menu_upload)
				.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);

		// settings = menu.add(0, 3, 3,
		// R.string.action_settings).setIcon(android.R.drawable.ic_menu_preferences)
		// .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_NEVER |
		// MenuItem.SHOW_AS_ACTION_WITH_TEXT);

		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case 1:
				refresh();
				break;
			case 2:
				uploadTorrent();
				break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onPause() {
		cleanMessages();
		removeObservers();
		super.onPause();
	}

	@Override
	public void onResume() {
		addObservers();
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d("mLastRefreshTime", "onResume:\t" + mLastRefreshTime);
		}
		final long remaining = mLastRefreshTime + mRefreshTime * 1000L - System.currentTimeMillis();
		if (remaining < 0) {
			refresh();
		} else {
			setNextRefresh(remaining);
		}
		super.onResume();
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {

		outState.putSerializable(STATE_TORRENTS, prepareToSerialize(mTorrents));
		outState.putLong(STATE_LAST_REFRESH_TIME, mLastRefreshTime);
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d("mLastRefreshTime", "onSavedIn:\t" + mLastRefreshTime);
		}
		super.onSaveInstanceState(outState);
	}

	@Override
	public void onStart() {
		if (!mManager.hasInitClient() || mManager.IsClientShouldBeInit()) {
			if (!mManager.initTransmissionclient()) {
				showUpdateSettingsDialog();
			}
			cleanMessages();

		}
		super.onStart();
	}

	public void refresh() {
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d("mLastRefreshTime", "Launch refresh");
		}
		if (isAdded()) {
			if (mManager.hasInitClient()) {
				getSherlockActivity().setSupportProgressBarIndeterminateVisibility(true);
				mManager.getTorrentList();

			}
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public void update(Observable observable, Object data) {

		if (observable instanceof TransmissionManager) {
			getSherlockActivity().setSupportProgressBarIndeterminateVisibility(false);
			TransmissionResult result = (TransmissionResult) data;
			if (result.mAction == ActionType.GetTorrent) {
				mLastRefreshTime = System.currentTimeMillis();
				if (Config.DEBUG_MODE_ENABLED) {
					Log.d("mLastRefreshTime", "update:\t" + mLastRefreshTime);
				}
				setNextRefresh(mRefreshTime * 1000);
			} else {
				cleanMessages();
				setNextRefresh(500);
			}
			if (ResultType.SUCCESS == result.mSuccess && result.mAction == ActionType.GetTorrent) {
				mTorrents = (ArrayList<TorrentStatus>) result.mData;
				mTorrentListAdapter.setTorrents(mTorrents);
			}
		}

	}

	private void cleanMessages() {
		if (mHandler.hasMessages(MESSAGE_ID)) {
			mHandler.removeMessages(MESSAGE_ID);
		}
	}

	// method pour supprimer un torrent
	private void deleteTorrent(final int torrentId) {
		if (mManager.hasInitClient()) {
			AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity());
			LayoutInflater inflater = (LayoutInflater) getSherlockActivity().getSystemService(
					Context.LAYOUT_INFLATER_SERVICE);
			final View v = inflater.inflate(R.layout.layout_dialog_delete, null);
			CheckBox checkbox = (CheckBox) v.findViewById(R.id.diag_checkbox);

			checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

				@Override
				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
					mForceLocalFileDeletion = isChecked;

				}

			});
			builder.setTitle(R.string.dialog_delete_torrent_title).setView(v)
					.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							mManager.removeTorrent(torrentId, mForceLocalFileDeletion);

						}
					}).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();

						}
					}).show().setCancelable(true);
		}
	}

	/** Récupère la liste de torrents et la serialize pour la sauvegarder lors d'un changement d'orientation. */
	private ArrayList<String> prepareToSerialize(ArrayList<TorrentStatus> arrayList) {
		final ArrayList<String> jsonArray = new ArrayList<String>();
		if (arrayList != null)
			for (TorrentStatus string : arrayList) {
				jsonArray.add(string.toString());
			}
		return jsonArray;
	}

	private void setNextRefresh(long time) {
		cleanMessages();
		mHandler.sendEmptyMessageDelayed(MESSAGE_ID, time);
	}

	/**
	 * Affiche la boite de dialogue demandant de paramétrer les settings si on n'arrive pas à se connecter pour
	 * récupérer les torrents.
	 */
	private void showUpdateSettingsDialog() {
		if (!mUpdateSettingsAlreadyShown) {
			mUpdateSettingsAlreadyShown = true;
			AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
			builder.setTitle(R.string.couldnt_connect);
			builder.setMessage(R.string.check_settings);
			builder.setCancelable(true);
			builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int arg1) {
					startActivity(new Intent(getActivity(), SettingsActivity.class));
					dialog.dismiss();
				}
			});
			builder.setNegativeButton("Later", new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int arg1) {
					dialog.dismiss();
				}
			});
			builder.show();

		}
	}

	private ArrayList<TorrentStatus> transform(ArrayList<String> fromSerializeJson) {
		final ArrayList<TorrentStatus> tStatusArray = new ArrayList<TorrentStatus>();
		if (fromSerializeJson != null)
			for (String json : fromSerializeJson) {
				tStatusArray.add(new TorrentStatus(new JSONObject(json)));
			}
		return tStatusArray;
	}

	/**
	 * Display the activity to choose a file. You can pass a filter.
	 */
	private void uploadTorrent() {
		if (mManager.hasInitClient()) {
			Intent intent = new Intent(getActivity(), FileChooserActivity.class);
			intent.putExtra(FileChooserActivity.EXTRA_NAME_FILTER, ".torrent");
			startActivityForResult(intent, FileChooserActivity.REQUEST_CHOOSE_FILE);
		}
	}

	protected void addObservers() {
		for (final Observable obs : mLstObservable) {
			obs.addObserver(this);
		}
	}

	protected void removeObservers() {
		for (final Observable obs : mLstObservable) {
			obs.deleteObserver(this);
		}
	}

	private final class TorrentActionModes implements ActionMode.Callback {

		public static final int DELETE = Menu.FIRST + 2;
		public static final int PAUSE = Menu.FIRST + 1;
		public static final int PLAY = Menu.FIRST;
		int mSelectedItem = 0;

		public TorrentActionModes(int selectedItem) {
			super();
			mSelectedItem = selectedItem;
		}

		@Override
		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
			handlerAction(item.getItemId());
			mode.finish();
			return true;
		}

		@Override
		public boolean onCreateActionMode(ActionMode mode, Menu menu) {

			menu.add(0, PLAY, 1, R.string.action_play).setIcon(R.drawable.ic_media_play)
					.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);

			menu.add(0, PAUSE, 2, R.string.action_pause).setIcon(R.drawable.ic_media_pause)
					.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);

			menu.add(0, DELETE, 3, R.string.action_delete).setIcon(R.drawable.ic_menu_close_clear_cancel)
					.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);

			return true;
		}

		@Override
		public void onDestroyActionMode(ActionMode mode) {
		}

		@Override
		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
			return false;
		}

		private void handlerAction(int menuId) {
			switch (menuId) {
				case PLAY:
					if (mManager.hasInitClient()) {
						mManager.startTorrent(mSelectedItem);
					}
					break;
				case PAUSE:
					if (mManager.hasInitClient()) {
						mManager.stopTorrent(mSelectedItem);
					}
					break;
				case DELETE:
					deleteTorrent(mSelectedItem);
					break;

				default:
					Toast.makeText(getSherlockActivity(), "Action unknown", Toast.LENGTH_SHORT).show();
					break;
			}
		}
	}

	class TorrentListAdapter extends BaseAdapter implements OnItemClickListener, OnItemLongClickListener {

		LayoutInflater inflater;

		Activity mActivity;
		ArrayList<TorrentStatus> torrents;

		public TorrentListAdapter(Activity activity) {
			torrents = new ArrayList<TorrentStatus>();
			mActivity = activity;
			inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		@Override
		public int getCount() {
			return torrents.size();
		}

		@Override
		public TorrentStatus getItem(int position) {
			return torrents.get(position);
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = inflater.inflate(R.layout.listitem_torrents, null);
				holder.mTextView = (TextView) convertView.findViewById(R.id.listitem_torrent_title);
				holder.mProgressBar = (ProgressBar) convertView.findViewById(R.id.listitem_torrent_progress);
				holder.mToggleButton = (ImageView) convertView.findViewById(R.id.listitem_torrent_resume_pause);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			TorrentStatus torrentstatus = getItem(position);
			TStatus status = torrentstatus.getStatus();
			holder.mTextView.setText(torrentstatus.getName());
			Number percent = torrentstatus.getPercentDone() * 100;
			holder.mProgressBar.setProgress(percent.intValue());
			if (status == TStatus.Downloading || status == TStatus.Checking || status == TStatus.Seeding) {
				holder.mToggleButton.setImageResource(R.drawable.ic_media_pause);
			} else {
				holder.mToggleButton.setImageResource(R.drawable.ic_media_play);
			}

			return convertView;
		}

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

			String json = getItem(position).toString();
			startActivity(new Intent(getSherlockActivity(), TorrentActivity.class).putExtra(
					TorrentActivity.TORRENT_JSON, json));
		}

		@Override
		public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
			TorrentStatus torrentstatus = getItem(position);

			getSherlockActivity().startActionMode(new TorrentActionModes(torrentstatus.getId()));
			return true;
		}

		public void setTorrents(ArrayList<TorrentStatus> torrentss) {
			torrents = torrentss;
			notifyDataSetChanged();
		}

		class ViewHolder {
			ProgressBar mProgressBar;
			TextView mTextView;
			ImageView mToggleButton;

		}

	}
}
